/**
 * 针对武汉建行数据中心怀疑内存值发生变化导致文件md5问题，设计检测内存数值程序
 * @file cpuAffinity.c
 * @author yeqiang
 * @brief
 * @version 0.1
 * @date 2022-23-28
 * @copyright Copyright (c) 2022
 *
 */
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sched.h>
#include <errno.h>
#include <pthread.h>

#define MAX_THREAD_NUM 1
// 1GB
#define BUFFER_SIZE 1024

void printhexDump(const char *buffer, size_t len)
{
    if (buffer == NULL || len <= 0)
    {
        return;
    }
    printf("0x%lxd: (len=%d)[", buffer, len);
    for (size_t i = 0; i < len; i++)
    {
        printf("%.2X ", (unsigned char)buffer[i]);
    }
    printf("]\n");
}

void *memoryTest(void *arg)
{
    unsigned int counter = 0;
    // 传递过来的是指针的指针
    printf("@%lxd\n", arg);
    unsigned long *pp = (unsigned long *)arg;
    // pv才是指针的值
    unsigned long pv = *pp;
    printf("%lxd\n", pv);

    void *realPoint = (void *)pv;
    printhexDump(realPoint, 1024);
    unsigned long maxLong = 0xFFFFFFFFFFFFFFFF;
    unsigned long *longPoint = realPoint;
    unsigned long *checkLongPoint = 0;
    unsigned long checkLong = 0;
    while (1)
    {
        // 每8字节扫描一次
        for (int i = 0; i < BUFFER_SIZE / 8; i++)
        {
            checkLongPoint = longPoint + i * 8;
            printf("\rchecking i=%d, @%lxd", i, checkLongPoint);
            checkLong = *(checkLongPoint);
            if (checkLong != maxLong)
            {
                printf("check Error");
                printhexDump((const char *)checkLongPoint, 1024);
                exit(1);
            }
        }
        printf("finished counter = %d\n", ++counter);
    }
}

int main(int argc, char *argv[])
{
    pthread_t threads[MAX_THREAD_NUM]; // 一个node最多64G
    void *points[MAX_THREAD_NUM];
    if (argc != 4)
    {
        printf("usage: numactl -N nodeId -M nodeId memtest4ft2000+\n");
        // return 1;
    }
    int err;
    for (int i = 0; i < MAX_THREAD_NUM; i++)
    {
        void *p = malloc(BUFFER_SIZE); // 1G
        if (p)
        {
            printf("malloc %ld at %lxd\n", BUFFER_SIZE, p);
            // 內存全部bit位初始化为1
            memset(p, 255, BUFFER_SIZE);
            // 打印前1KB
            printhexDump(p, 1024);
            points[i] = p;
            err = pthread_create(&threads[i], NULL, memoryTest, &points[i]);
            if (err != 0)
            {
                printf("can’t create thread: %s\n", strerror(err));
                return 1;
            }
        }
        else
        {
            break;
        }
    }
    while (1)
    {
        sleep(999999);
    }
}